﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using PropertyMetadata = System.Windows.PropertyMetadata;

namespace YY.Admin.Core.Helper
{
    /// <summary>
    /// ScrollViewer 辅助类：
    /// 解决 ScrollViewer 包裹 TreeView / ListBox 等控件时，
    /// 鼠标滚轮在内部控件上无法触发外层 ScrollViewer 滚动的问题。
    /// </summary>
    public static class ScrollViewerHelper
    {
        /// <summary>
        /// 附加属性：是否启用鼠标滚轮事件向上传递
        /// </summary>
        public static readonly DependencyProperty EnableMouseWheelPropagationProperty =
            DependencyProperty.RegisterAttached(
                "EnableMouseWheelPropagation",              // 属性名
                typeof(bool),                               // 属性类型
                typeof(ScrollViewerHelper),                 // 所属类型
                new PropertyMetadata(false, OnEnableMouseWheelPropagationChanged)); // 默认值+回调

        /// <summary>
        /// 获取附加属性值（XAML 绑定/读取）
        /// </summary>
        public static bool GetEnableMouseWheelPropagation(DependencyObject obj)
            => (bool)obj.GetValue(EnableMouseWheelPropagationProperty);

        /// <summary>
        /// 设置附加属性值（XAML 设置）
        /// </summary>
        public static void SetEnableMouseWheelPropagation(DependencyObject obj, bool value)
            => obj.SetValue(EnableMouseWheelPropagationProperty, value);

        /// <summary>
        /// 当附加属性值发生变化时触发
        /// </summary>
        private static void OnEnableMouseWheelPropagationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is UIElement element)
            {
                // 如果启用，则订阅 PreviewMouseWheel 事件
                if ((bool)e.NewValue)
                    element.PreviewMouseWheel += Element_PreviewMouseWheel;
                else
                    // 否则移除事件
                    element.PreviewMouseWheel -= Element_PreviewMouseWheel;
            }
        }

        /// <summary>
        /// 当鼠标滚轮在目标控件上滚动时触发，
        /// 将事件手动冒泡到上层（如 ScrollViewer）以实现滚动。
        /// </summary>
        private static void Element_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            // 若事件已被处理，则直接返回
            if (e.Handled) return;

            // 标记事件已处理，防止重复触发
            e.Handled = true;

            // 构造一个新的 MouseWheelEventArgs，用于向父级转发
            var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
            {
                RoutedEvent = UIElement.MouseWheelEvent, // 指定为标准鼠标滚轮事件
                Source = sender                          // 来源设为当前控件
            };

            // 获取父元素，并将事件重新抛出
            if (sender is Control control)
            {
                var parent = control.Parent as UIElement;
                parent?.RaiseEvent(eventArg);
            }
        }
    }
}
